import { ipcMain } from 'electron'
import http from 'http'
import https from 'https'
import net from 'net'
import tls from 'tls'
import { createCertificate, createServerCertificate } from './certManager'
import SystemProxyManager from './systemProxyManager'
import path from 'path'
import fs from 'fs'
import { exec } from 'child_process'
import { promisify } from 'util'
import os from 'os'

const execAsync = promisify(exec)
let proxyServer = null
const CERT_DIR = path.join(process.cwd(), 'certificates')
const CACHE_DIR = path.join(CERT_DIR, 'cache')

class ProxyHandler {

  // 将 installWindowsCertificate 移到类内部作为静态方法
  static async installWindowsCertificate(certPath) {
    try {
      // Check if certificate file exists
      if (!fs.existsSync(certPath)) {
        throw new Error(`Certificate file not found at ${certPath}`)
      }

      // Ensure path is absolute
      const absolutePath = path.resolve(certPath)
      
      // Run certutil with absolute path
      await execAsync(`certutil -addstore -user "Root" "${absolutePath}"`)
      return true
    } catch (error) {
      console.error('Certificate installation failed:', error)
      throw error
    }
  }

  // 添加 Mac 证书安装方法
  static async installMacCertificate(certPath) {
    try {
      await execAsync(`security add-trusted-cert -d -r trustRoot -k ~/Library/Keychains/login.keychain "${certPath}"`)
      return true
    } catch (error) {
      console.error('安装证书失败:', error)
      throw error
    }
  }

  static async installCertificate() {
    const certPath = path.join(CERT_DIR, 'rootCA.crt')
    const keyPath = path.join(CERT_DIR, 'rootCA.key')
    
    try {
      // Ensure certificate directory exists
      if (!fs.existsSync(CERT_DIR)) {
        fs.mkdirSync(CERT_DIR, { recursive: true })
      }

      // Create root certificate if it doesn't exist
      if (!fs.existsSync(certPath) || !fs.existsSync(keyPath)) {
        console.log('Creating new root certificate...')
        const { cert, key } = await createCertificate()
        fs.writeFileSync(certPath, cert)
        fs.writeFileSync(keyPath, key)
      }

      // Verify certificate exists
      if (!fs.existsSync(certPath)) {
        throw new Error('Root certificate not found after creation attempt')
      }

      const platform = os.platform()
      
      if (platform === 'win32') {
        return await this.installWindowsCertificate(certPath)
      } else if (platform === 'darwin') {
        return await this.installMacCertificate(certPath)
      }
      
      return false
    } catch (error) {
      console.error('Certificate installation failed:', error)
      throw error
    }
  }

  static async getOrCreateCertificate(hostname) {
    const certFile = path.join(CACHE_DIR, `${hostname}.crt`)
    const keyFile = path.join(CACHE_DIR, `${hostname}.key`)
    
    try {
      // Check certificate cache
      if (fs.existsSync(certFile) && fs.existsSync(keyFile)) {
        console.log(`Using cached certificate for ${hostname}`)
        return {
          cert: fs.readFileSync(certFile),
          key: fs.readFileSync(keyFile)
        }
      }
  
      console.log(`Generating new certificate for ${hostname}`)
  
      // Read root certificate
      const rootCert = fs.readFileSync(path.join(CERT_DIR, 'rootCA.crt'), 'utf8')
      const rootKey = fs.readFileSync(path.join(CERT_DIR, 'rootCA.key'), 'utf8')
      
      // Generate server certificate
      const serverCert = await createServerCertificate(hostname, rootCert, rootKey)
      
      if (!serverCert || !serverCert.cert || !serverCert.key) {
        throw new Error('Failed to generate server certificate - invalid certificate data')
      }
  
      // Save to cache
      fs.writeFileSync(certFile, serverCert.cert)
      fs.writeFileSync(keyFile, serverCert.key)
      
      return serverCert
    } catch (error) {
      console.error('Certificate generation error:', error)
      console.error('Hostname:', hostname)
      console.error('Certificate directory exists:', fs.existsSync(CERT_DIR))
      console.error('Cache directory exists:', fs.existsSync(CACHE_DIR))
      throw error
    }
  }

  static createHttpsServer(hostname, event) {
    return new Promise(async (resolve, reject) => {
      try {
        const { cert, key } = await ProxyHandler.getOrCreateCertificate(hostname)
        
        const httpsServer = https.createServer({
          cert,
          key,
          rejectUnauthorized: false
        }, async (req, res) => {
          const requestId = Date.now().toString()
          let requestBody = ''
  
          req.on('data', chunk => {
            requestBody += chunk
          })
  
          req.on('end', () => {
            // Construct target URL while maintaining original URL structure
            const targetUrl = `https://${req.headers.host}${req.url}`
            
            // Clean up headers while preserving essential ones
            const headers = {...req.headers}
            delete headers['proxy-connection']
  
            // Send request info to renderer before forwarding
            event.sender.send('proxy:request', {
              id: requestId,
              url: targetUrl,
              method: req.method,
              headers: headers,
              body: requestBody,
              timestamp: Date.now()
            })
  
            const proxyReq = https.request(targetUrl, {
              method: req.method,
              headers: headers,
              rejectUnauthorized: false
            }, (proxyRes) => {
              // Clean up response headers
              const responseHeaders = {...proxyRes.headers}
              delete responseHeaders['strict-transport-security']
              
              // Set response headers first
              res.writeHead(proxyRes.statusCode, responseHeaders)
  
              // Track response body for logging
              let responseBody = ''
              proxyRes.on('data', chunk => {
                responseBody += chunk.toString()
                // Forward chunk immediately to maintain streaming
                res.write(chunk)
              })
  
              proxyRes.on('end', () => {
                // Send response info to renderer
                event.sender.send('proxy:response', {
                  id: requestId,
                  statusCode: proxyRes.statusCode,
                  headers: responseHeaders,
                  body: responseBody,
                  timestamp: Date.now()
                })
                // End the response
                res.end()
              })
            })
  
            proxyReq.on('error', (err) => {
              console.error('HTTPS proxy request error:', err)
              res.writeHead(502)
              res.end('Proxy Error: ' + err.message)
            })
  
            if (requestBody) {
              proxyReq.write(requestBody)
            }
            proxyReq.end()
          })
        })
  
        httpsServer.on('error', (err) => {
          console.error('HTTPS server error:', err)
          reject(err)
        })
  
        httpsServer.listen(0, '127.0.0.1', () => {
          resolve(httpsServer)
        })
      } catch (error) {
        reject(error)
      }
    })
  }

  static async stopProxy() {
    try {
      if (proxyServer) {
        // 先移除系统代理
        await SystemProxyManager.removeSystemProxy()
        // 然后关闭代理服务器
        proxyServer.close()
        proxyServer = null
        return { success: true, message: 'Proxy server stopped and system proxy removed' }
      }
      return { success: true, message: 'Proxy server not running' }
    } catch (error) {
      console.error('停止代理服务器时出错:', error)
      // 即使出错也尝试清理系统代理
      try {
        await SystemProxyManager.removeSystemProxy()
      } catch (cleanupError) {
        console.error('清理系统代理时出错:', cleanupError)
      }
      throw error
    }
  }

  static register() {
    // 确保证书目录存在
    if (!fs.existsSync(CERT_DIR)) {
      fs.mkdirSync(CERT_DIR, { recursive: true })
    }
    if (!fs.existsSync(CACHE_DIR)) {
      fs.mkdirSync(CACHE_DIR, { recursive: true })
    }

    // 启动代理服务器
    ipcMain.handle('proxy:start', async (event, port = 8001) => {
      try {
        if (proxyServer) {
          return { success: false, error: 'Proxy server already running' }
        }

        // 修改系统代理设置
        const proxyBypassList = [
          'localhost',
          '127.0.0.1',
          '*.local',
          '*.localhost',
          '<local>'
        ].join(';')

        // 设置系统代理时添加绕过规则
        const success = await SystemProxyManager.setSystemProxy('127.0.0.1', port, proxyBypassList)
        if (!success) {
          throw new Error('Failed to set system proxy')
        }

        // 创建HTTP代理服务器
        proxyServer = http.createServer((req, res) => {
          const requestId = Date.now().toString()
          let requestBody = ''

          req.on('data', chunk => {
            requestBody += chunk
          })

          req.on('end', () => {
            const targetUrl = req.url.startsWith('http') ? req.url : `http://${req.headers.host}${req.url}`
            const parsedUrl = new URL(targetUrl)

            event.sender.send('proxy:request', {
              id: requestId,
              url: targetUrl,
              method: req.method,
              headers: req.headers,
              body: requestBody,
              timestamp: Date.now()
            })

            const proxyReq = http.request({
              protocol: parsedUrl.protocol,
              hostname: parsedUrl.hostname,
              port: parsedUrl.port || 80,
              path: parsedUrl.pathname + parsedUrl.search,
              method: req.method,
              headers: req.headers
            }, (proxyRes) => {
              let responseBody = ''

              proxyRes.on('data', chunk => {
                responseBody += chunk
              })

              proxyRes.on('end', () => {
                event.sender.send('proxy:response', {
                  id: requestId,
                  statusCode: proxyRes.statusCode,
                  headers: proxyRes.headers,
                  body: responseBody,
                  timestamp: Date.now()
                })
              })

              res.writeHead(proxyRes.statusCode, proxyRes.headers)
              proxyRes.pipe(res)
            })

            proxyReq.on('error', (err) => {
              console.error('HTTP proxy request error:', err)
              res.writeHead(500)
              res.end('Proxy Error')
            })

            if (requestBody) {
              proxyReq.write(requestBody)
            }
            proxyReq.end()
          })
        })

        // 处理HTTPS请求
        proxyServer.on('connect', async (req, clientSocket, head) => {
          const [hostname, targetPort] = req.url.split(':')
          const port = parseInt(targetPort) || 443

          console.log('HTTPS 连接请求:', {
            hostname,
            targetPort,
            headers: req.headers
          })

          try {
            const httpsServer = await ProxyHandler.createHttpsServer(hostname, event)
            const { port: httpsPort } = httpsServer.address()

            console.log('HTTPS 服务器创建成功:', {
              httpsPort,
              hostname
            })

            clientSocket.write('HTTP/1.1 200 Connection Established\r\n\r\n')

            const connection = net.connect({
              port: httpsPort,
              host: '127.0.0.1'
            }, () => {
              console.log('HTTPS 隧道建立成功')
              connection.write(head)
              connection.pipe(clientSocket)
              clientSocket.pipe(connection)
            })

            connection.on('error', (err) => {
              console.error('HTTPS 连接错误:', err)
              clientSocket.end()
            })

            clientSocket.on('error', (err) => {
              console.error('Client socket error:', err)
              connection.end()
            })

            clientSocket.on('end', () => {
              connection.end()
              httpsServer.close()
            })

            connection.on('end', () => {
              console.log('HTTPS 连接结束')
              clientSocket.end()
              httpsServer.close()
            })

            connection.on('connect', () => {
              console.log('HTTPS 隧道连接成功')
            })
        
            connection.on('data', (data) => {
              console.log('HTTPS 数据传输:', data.length, 'bytes')
            })

          } catch (error) {
            console.error('HTTPS tunnel error:', error)
            console.error('HTTPS 隧道错误:', error)
            clientSocket.end()
          }
        })

        proxyServer.on('error', (err) => {
          console.error('Proxy server error:', err)
          event.sender.send('proxy:error', { error: err.message })
        })

        // 启动代理服务器
        await new Promise((resolve) => {
          proxyServer.listen(port, '0.0.0.0', () => {
            resolve()
          })
        })

        // 设置系统代理
        const success2 = await SystemProxyManager.setSystemProxy('127.0.0.1', port)
        if (!success2) {
          throw new Error('Failed to set system proxy')
        }

        event.sender.send('proxy:status', { 
          status: 'ready', 
          port 
        })

        return { success: true, message: 'Proxy server started' }
      } catch (error) {
        if (proxyServer) {
          proxyServer.close()
          proxyServer = null
        }
        await SystemProxyManager.removeSystemProxy()
        return { success: false, error: error.message }
      }
    })

    // 停止代理服务器
    ipcMain.handle('proxy:stop', async () => {
      try {
        if (proxyServer) {
          proxyServer.close()
          proxyServer = null
          await SystemProxyManager.removeSystemProxy()
          return { success: true, message: 'Proxy server stopped' }
        }
        return { success: false, error: 'Proxy server not running' }
      } catch (error) {
        try {
          await SystemProxyManager.removeSystemProxy()
        } catch (cleanupError) {
          console.error('清理系统代理时出错:', cleanupError)
        }

        return { success: false, error: error.message }
      }
    })

    // 获取证书路径
    ipcMain.handle('proxy:getCertPath', () => {
      return path.join(CERT_DIR, 'rootCA.crt')
    })

    // 添加证书安装处理程序
    ipcMain.handle('proxy:installCert', async () => {
      try {
        const success = await ProxyHandler.installCertificate()
        return { success, message: success ? '证书安装成功' : '证书安装失败' }
      } catch (error) {
        return { success: false, error: error.message }
      }
    })

    // 测试证书
    ipcMain.handle('proxy:testCert', async (event, domain = 'www.baidu.com' ) => {
      try {
        // 测试证书
        const certTest = await ProxyHandler.testCertificate(domain)
        return { success: certTest, message: certTest ? '证书测试成功' : '证书不存在' }
      } catch (error) {
        return { success: false, error: error.message }
      }
    })

  }

  static async testCertificate(hostname) {
    try {
      const { cert } = await ProxyHandler.getOrCreateCertificate(hostname)
      const testServer = https.createServer({ cert }, (req, res) => {
        res.end('Certificate test successful')
      })
  
      return new Promise((resolve, reject) => {
        testServer.listen(0, '127.0.0.1', () => {
          const { port } = testServer.address()
          testServer.close(() => resolve(true))
        })
      })
      return true
    } catch (error) {
      console.error('证书测试失败:', error)
      return false
    }
  }
}

export default ProxyHandler